﻿using GetTogether.Studio.WebService;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Net;
using System.Web;
namespace GetTogether.Studio.WebService
{
    public class WebServiceProxy : IHttpHandler, System.Web.SessionState.IRequiresSessionState
    {
        public const string Suffix = ".proxy";
        public bool IsReusable
        {
            get
            {
                return false;
            }
        }

        private void WritePlainText(HttpContext context, string msg, bool isError)
        {
            context.Response.ContentType = "text/plain";
            context.Response.Write(msg);
            if (isError) GetTogether.Studio.Log.Error(new Exception(msg));
            context.Response.End();
        }

        public void ProcessRequest(HttpContext context)
        {
            #region Validate
            string[] paramInfo = new System.Text.RegularExpressions.Regex(
               WebServiceProxyHelper.GetRootURI(context.Request), System.Text.RegularExpressions.RegexOptions.IgnoreCase)
                .Replace(context.Request.Url.AbsoluteUri, "").Split('?')[0].Split('/');
            if (paramInfo.Length < 2)
            {
                WritePlainText(context, "Invalid parameter", true);
            }
            string ProjectName = paramInfo[1];
            ProjectName = System.Web.HttpUtility.UrlDecode(ProjectName);
            ProjectName = new System.Text.RegularExpressions.Regex(
                 string.Concat(@"\", Suffix), System.Text.RegularExpressions.RegexOptions.IgnoreCase)
                 .Replace(ProjectName, "");
            string UserCode = paramInfo[0];
            UserCode = System.Web.HttpUtility.UrlDecode(UserCode);
            if (string.IsNullOrEmpty(ProjectName))
            {
                WritePlainText(context, "Invalid project name", true);
            }
            else if (string.IsNullOrEmpty(UserCode))
            {
                WritePlainText(context, "Invalid user", true);
            }
            #endregion
            #region Special Action
            string action = context.Request["action"];
            if (!string.IsNullOrEmpty(action))
            {
                action = action.Trim().ToUpper();
                if (action=="CLEAR-CACHE")
                {
                    string prefixCacheKey = string.Concat("Proxy", "|", UserCode, "|", ProjectName, "|");
                    System.Web.Caching.Cache _cache = HttpRuntime.Cache;
                    IDictionaryEnumerator cacheEnum = _cache.GetEnumerator();
                    Dictionary<string, List<string>> ret = new Dictionary<string, List<string>>();
                    while (cacheEnum.MoveNext())
                    {
                        string key = cacheEnum.Key.ToString();
                        if (key.StartsWith(prefixCacheKey))
                        {
                            GetTogether.Web.CacheHelper.RemoveCache(key);
                        }
                    }
                    WritePlainText(context, "All caches has been cleared", false);
                }
            }
            #endregion
            context.Response.ContentType = "text/xml";
            ProjectParameter parameter = ProjectParameter.GetSettingsByProjectName(UserCode, ProjectName, UserCode);
            if (parameter == null)
            {
                WritePlainText(context, "Project not found", true);
            }
            GetTogether.Studio.ProjectHistory.SaveHistory(Studio.ProjectParameter.ProjectCategory.WebService, ProjectName, UserCode,DateTime.MinValue,DateTime.Now);
            string requestXml = GetTogether.Web.WebHelper.GetRequestInputString(context.Request);
            if (!string.IsNullOrEmpty(context.Request["WSDL"]) || string.IsNullOrEmpty(requestXml))
            {
                System.Net.WebClient wc = new System.Net.WebClient();
                wc.Encoding = System.Text.Encoding.UTF8;
                string wsdlAddress = parameter.WsdlAddress;
                if (string.IsNullOrEmpty(wsdlAddress)) wsdlAddress = string.Concat(parameter.Address, parameter.Address.IndexOf("?") > 0 ? "&" : "?", "WSDL");
                context.Response.Write(wc.DownloadString(wsdlAddress));
                context.Response.End();
            }
            string methodName = "";
            if (parameter.AddressType == AddressType.WebService)
                methodName = WebServiceProxyHelper.GetMethodName(requestXml);
            else
                methodName = "SendRequest";
            bool enableCache = false;
            if (parameter.Proxy != null) enableCache = parameter.Proxy.EnableCache;
            string responseXml = string.Empty;
            #region Proxy Case
            string proxyPath = WebServiceProxyHelper.GetProxyPath(UserCode, parameter.ProjectName, methodName);
            if (System.IO.Directory.Exists(proxyPath))
            {
                foreach (string proxyCase in System.IO.Directory.GetDirectories(proxyPath))
                {
                    ProxyCaseParameter proxyParam = GetTogether.Utility.SerializationHelper.FromXml<ProxyCaseParameter>(
                        System.IO.File.ReadAllText(System.IO.Path.Combine(proxyCase, "Parameter.txt"), System.Text.Encoding.UTF8));
                    if (!string.IsNullOrEmpty(proxyParam.Regular))
                    {
                        System.Text.RegularExpressions.Match m = new System.Text.RegularExpressions.Regex(proxyParam.Regular, System.Text.RegularExpressions.RegexOptions.None).Match(requestXml);
                        if (m.Success)
                        {
                            responseXml = System.IO.File.ReadAllText(System.IO.Path.Combine(proxyCase, "Response.txt"), System.Text.Encoding.UTF8);
                            context.Response.Write(responseXml);
                            context.Response.End();
                        }
                    }
                    else if (requestXml == System.IO.File.ReadAllText(System.IO.Path.Combine(proxyCase, "Request.txt")))
                    {
                        responseXml = System.IO.File.ReadAllText(System.IO.Path.Combine(proxyCase, "Response.txt"), System.Text.Encoding.UTF8);
                        context.Response.Write(responseXml);
                        context.Response.End();
                    }
                }
            }
            #endregion
            string cacheKey = string.Concat("Proxy", "|", UserCode, "|", parameter.ProjectName, "|", methodName, "|", requestXml);
            if (enableCache)
            {
                responseXml = (string)GetTogether.Web.CacheHelper.GetCache(cacheKey);
                if (!string.IsNullOrEmpty(responseXml))
                {
                    context.Response.Write(responseXml);
                    context.Response.End();
                }
            }
            GetTogether.Studio.WebService.NormalRequest nr = new GetTogether.Studio.WebService.NormalRequest();
            nr.Url = parameter.Address;

            responseXml = nr.SendRequest(requestXml, new GetTogether.Studio.WebService.RequestProperty());
            if (enableCache)
            {
                GetTogether.Web.CacheHelper.SetCache(cacheKey, responseXml);
            }
            context.Response.Write(responseXml);
            context.Response.End();
        }
    }
}